﻿using ResxHelper.Logic.Readers;
using ResxHelper.Object;

namespace ResxHelper.Logic
{
    public class MergeFacade
    {
        public static ResourceFile Merge(ResourceFile original, ResourceFile imported, MergeOption option = MergeOption.Full)
        {
            var copy = original.Clone();
            switch (option)
            {
                case MergeOption.AddOnly:
                    copy = MergeAddOnly(copy, imported);
                    break;
                case MergeOption.UpdateOnly:
                    copy = MergeUpdateOnly(copy, imported);
                    break;
                case MergeOption.DeleteOnly:
                    copy = MergeDeleteOnly(copy, imported);
                    break;
                case MergeOption.AddAndDelete:
                    copy = MergeAddAndDelete(copy, imported);
                    break;
                case MergeOption.AddAndOverwrite:
                    copy = MergeUpdateAndAdd(copy, imported);
                    break;
                case MergeOption.Full:
                    copy = MergeFull(copy, imported);
                    break;
            }
            return copy;
        }

        public static ResourceFile Merge(ResourceFile original, string importedCsvPath, MergeOption option = MergeOption.AddAndOverwrite)
        {
            var imported = ResourceFileReaderFactory.GetReader(importedCsvPath, ResourceType.Csv).Read();
            return Merge(original, imported);
        }

        public static ResourceFile Merge(string origincalCsvPath, string importedCsvPath, MergeOption option = MergeOption.AddAndOverwrite)
        {
            var originalResource = ResourceFileReaderFactory.GetReader(origincalCsvPath, ResourceType.Csv).Read();
            var importedResource = ResourceFileReaderFactory.GetReader(importedCsvPath, ResourceType.Csv).Read();
            return Merge(originalResource, importedResource);
        }

        public static ResourceFile MergeUpdateAndAdd(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();
            copy = MergeUpdateOnly(copy, imported);
            copy = MergeAddOnly(copy, imported);
            return copy;
        }

        public static ResourceFile MergeAddAndDelete(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();
            copy = MergeDeleteOnly(copy, imported);
            copy = MergeAddOnly(copy, imported);
            return copy;
        }

        public static ResourceFile MergeAddOnly(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();
            foreach (var entry in imported.Entries)
            {
                if (!copy.Entries.ContainsKey(entry.Key))
                {
                    copy.Entries.Add(entry.Key, entry.Value);
                }
            }
            return copy;
        }

        public static ResourceFile MergeUpdateOnly(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();
            foreach (var entry in imported.Entries)
            {
                if (copy.Entries.ContainsKey(entry.Key))
                {
                    copy.Entries[entry.Key].Value = entry.Value.Value;
                }
            }
            return copy;
        }

        public static ResourceFile MergeDeleteOnly(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();
            foreach (var entry in original.Entries)
            {
                if (!imported.Entries.ContainsKey(entry.Key))
                {
                    copy.Entries.Remove(entry.Key);
                }
            }
            return copy;
        }

        public static ResourceFile MergeUpdateAndDelete(ResourceFile original, ResourceFile imported)
        {
            // remove obsolete keys
            var copy = MergeDeleteOnly(original, imported).Clone();

            // update everything else
            copy = MergeUpdateOnly(copy, imported);
            return copy;
        }

        public static ResourceFile MergeFull(ResourceFile original, ResourceFile imported)
        {
            var copy = original.Clone();

            // remove obsolete keys
            copy = MergeDeleteOnly(copy, imported);

            // add missing keys
            copy = MergeAddOnly(copy, imported);

            // update everything else
            copy = MergeUpdateOnly(copy, imported);

            return copy;
        }
    }
}
